#ifndef __INTERVAL_
#define __INTERVAL_

#include "bool_interval.h"
#include "interval_from_real.h"
#include "mymath.h"
#include <cassert>

class Interval {
public:
    Interval(double a, double b);
    ~Interval() {}
    double a() const;
    double b() const;
    inline double unsafeA() const {
        return a();
    }
    inline double unsafeB() const {
        return b();
    }

    BoolInterval lt(const Interval& that) const;
    inline BoolInterval gt(const Interval& that) const {
        return that.lt(*this);  // 1<2在这里变成2>1
    }
    BoolInterval eq(const Interval& that) const;

    Interval sqrt() const;
    Interval isin() const;
    Interval icos() const;
    Interval itan() const;
    Interval ilog() const;

    Interval& operator+=(const Interval& that);
    Interval& operator-=(const Interval& that);
    Interval& operator*=(const Interval& that);
    Interval& operator/=(const Interval& that);

    Interval& operator++();  // ++a
    inline Interval operator++(int) {  // a++
        Interval old(*this);
        operator++();
        return old;
    }
    Interval& operator--();
    inline Interval operator--(int) {
        Interval old(*this);
        operator--();
        return old;
    }

    friend void swap(Interval& a, Interval& b);
    friend bool operator==(const Interval& l, const Interval& r);

private:
    double a_, b_;
    double Pi = 3.142592654;
    void assertInvariant() const;
    // Interval CreateIncludeInterval(const float& f);

};

inline Interval forceInterval(double a, double b) {
    return Interval(std::min(a, b), std::max(a, b));   // 矫正区间
}

// 显示具体化---具体化函数定义
template<>
inline Interval intervalFromReals<Interval>(double a, double b) {
    return forceInterval(a, b);
}

inline Interval operator+(Interval l, const Interval& r) {
    l += r;
    return l;
}
inline Interval operator-(Interval l, const Interval& r) {
    l -= r;
    return l;
}
inline Interval operator*(Interval l, const Interval& r) {
    l *= r;
    return l;
}
inline Interval operator/(Interval l, const Interval& r) {
    l /= r;
    return l;
}

extern const Interval allnan;

#endif

